package org.apache.dolphinscheduler.api.service.impl;

import org.apache.dolphinscheduler.api.dto.MonitorDto;
import org.apache.dolphinscheduler.api.enums.Status;
import org.apache.dolphinscheduler.api.service.ProductService;
import org.apache.dolphinscheduler.api.service.WorkerGroupService;
import org.apache.dolphinscheduler.api.utils.PageInfo;
import org.apache.dolphinscheduler.api.utils.Result;
import org.apache.dolphinscheduler.common.constants.Constants;
import org.apache.dolphinscheduler.dao.entity.Product;
import org.apache.dolphinscheduler.dao.entity.User;
import org.apache.dolphinscheduler.dao.mapper.ProductMapper;
import org.apache.dolphinscheduler.dao.mapper.ProductOrderItemMapper;
import org.apache.dolphinscheduler.dao.vo.ProductOrderItemVo;

import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author denggh
 * @since 2023-06-15
 */
@Service
public class ProductServiceImpl extends BaseServiceImpl implements ProductService {

    @Autowired
    private ProductMapper productMapper;
    @Autowired
    private ProductOrderItemMapper productOrderItemMapper;
    @Autowired
    private WorkerGroupService workerGroupService;
    @Override
    public Map<String, Object> selectProductById(Long productId) {
        Map<String, Object> result = new HashMap<>();
        Product product = productMapper.selectById(productId);
        if (product != null) {
            result.put(Constants.DATA_LIST, product);
            putMsg(result, Status.SUCCESS);
        }
        return result;
    }

    @Override
    public Map<String, Object> insertProduct(Product product) {
        Map<String, Object> result = new HashMap<>();
        int insert = productMapper.insert(product);
        if (insert > 0) {
            result.put(Constants.DATA_LIST, product);
            putMsg(result, Status.SUCCESS);
        }
        return result;
    }

    @Override
    public Map<String, Object> updateProduct(Product product) {
        Map<String, Object> result = new HashMap<>();
        int update = productMapper.updateById(product);
        if (update > 0) {
            putMsg(result, Status.SUCCESS);
        }
        return result;
    }

    @Override
    public Map<String, Object> deleteProductById(Long productId) {
        Map<String, Object> result = new HashMap<>();
        int delete = productMapper.deleteById(productId);
        if (delete > 0) {
            putMsg(result, Status.SUCCESS);
        }
        return result;
    }

    @Override
    public Result selectPageProductList(Product product, Integer pageSize, Integer pageNo, String searchVal,
                                        User loginUser) {
        Result result = new Result();

        if (!isAdmin(loginUser)) {
            result.setData(null);
            putMsg(result, Status.SUCCESS);
            return result;
        }
        PageInfo<Product> pageInfo = new PageInfo<>(pageNo, pageSize);

        Page<Product> page = new Page<>(pageNo, pageSize);

        IPage<Product> productIPage = null;
        LambdaQueryWrapper<Product> lqw = new LambdaQueryWrapper<Product>();
        if (StringUtils.isNotBlank(product.getHost())) {
            lqw.like(Product::getHost, product.getHost());
        }
        if (Objects.nonNull(product.getProductType())) {
            lqw.eq(Product::getProductType, product.getProductType());
        }
        if (Objects.nonNull(product.getProductSource())) {
            lqw.eq(Product::getProductSource, product.getProductSource());
        }
        if (Objects.nonNull(product.getBillType())) {
            lqw.eq(Product::getBillType, product.getBillType());
        }
        if (StringUtils.isNotBlank(searchVal)) {
            lqw.and(it -> it.like(Product::getProductName, searchVal)
                    .or()
                    .eq(Product::getvCpu, searchVal)
                    .or()
                    .like(Product::getProductNo, searchVal));
        }
        lqw.orderByDesc(Product::getDeployTime);
        productIPage = productMapper.selectPage(page, lqw);

        List<Product> productList = productIPage.getRecords();

        // 资源累计收入
        List<ProductOrderItemVo> productOrderItemVos = productOrderItemMapper.queryTotalIncome();
        Map<String, BigDecimal> itemMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(productOrderItemVos)) {
            itemMap = productOrderItemVos.stream()
                    .collect(Collectors.toMap(ProductOrderItemVo::getResourceNo, ProductOrderItemVo::getAmount));
        }
        for (Product product1 : productList) {
            BigDecimal amount = itemMap.get(product1.getProductNo());
            if (Objects.nonNull(amount)) {
                product1.setTotalIncome(amount);
            }
        }

        pageInfo.setTotal((int) productIPage.getTotal());
        pageInfo.setTotalList(productList);
        result.setData(pageInfo);
        putMsg(result, Status.SUCCESS);
        return result;
    }

    @Override
    public Map<String, Object> syncProduct() {
        Map<String, Object> result = new HashMap<>();

        // 查询资源表中所有数据
        List<Product> products = productMapper.selectList(new LambdaQueryWrapper<>());
        Set<String> hostList = new HashSet<>();
        Map<String, Integer> productMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(products)) {
            // 获取所有资源表中的host 按照host进行唯一标识判断
            productMap = products.stream().collect(Collectors.toMap(Product::getHost, Product::getId));
            hostList = productMap.keySet();
        }
        // 获取所有worker数据
        Map<String, MonitorDto> workerMonitorData = workerGroupService.queryWorkerMonitorData();
        Map<String, MonitorDto> workerMonitorDataNew = new HashMap<>();
        for (Map.Entry<String, MonitorDto> stringMonitorDtoEntry : workerMonitorData.entrySet()) {
            workerMonitorDataNew.put(stringMonitorDtoEntry.getKey().split(":")[0], stringMonitorDtoEntry.getValue());
        }
        List<Product> insertProductList = new ArrayList<>();
        List<Product> updateProductList = new ArrayList<>();
        int productNumber = 0;
        for (String host : workerMonitorDataNew.keySet()) {
            MonitorDto monitorDto = workerMonitorDataNew.get(host);
            Product product = new Product();
            // 设置worker相关配置信息
            product.setMemory(monitorDto.getMemorySize());
            product.setvCpu(monitorDto.getCpuNum());
            product.setDataTotal(monitorDto.getDataTotal());
            product.setProductName(monitorDto.getHostName());
            product.setDeployTime(monitorDto.getCreateTime());
            if (hostList.contains(host)) {
                // 更新资源配置
                product.setId(productMap.get(host));
                updateProductList.add(product);
            } else {
                // 新增资源
                product.setProductNo("" + System.currentTimeMillis() + productNumber++);
                product.setProductSource(0);
                product.setHost(host);
                product.setProductType(monitorDto.getIsVirtual());
                insertProductList.add(product);
            }
        }
        for (Product product : insertProductList) {
            productMapper.insert(product);
        }
        for (Product product : updateProductList) {
            productMapper.updateById(product);
        }
        putMsg(result, Status.SUCCESS);
        return result;
    }
}
